using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Text;
using System.Windows.Forms;

namespace Universe.WinForms
{
    public class SatisfactoryToolStripRenderer : ToolStripProfessionalRenderer
    {

        static Blend _MyBlend;
        static Blend _MyBackBlend;
        ToolStripButton[] _SpecialButtons;


        static SatisfactoryToolStripRenderer()
        {
            _MyBlend = new Blend();
            _MyBlend.Positions = new float[] { 0f, 0.7f, 0.85f, 1f };
            _MyBlend.Factors = new float[] { 0.0f, 0.3f, 0.4f, 1.0f };

            _MyBackBlend = new Blend();
            _MyBackBlend.Positions = new float[] { 0f, 0.15f, 0.3f, 1f };
            _MyBackBlend.Factors = new float[] { 0.0f, 0.8f, 0.9f, 1.0f };
        }

        public SatisfactoryToolStripRenderer(): base(new MyColorTable())
        {
        }


        private SatisfactoryToolStripRenderer(ToolStripButton[] specialButtons): this()
        {
            _SpecialButtons = specialButtons;
            if (_SpecialButtons == null)
                _SpecialButtons = new ToolStripButton[0];
        }


        public static void Bind(ToolStrip toolStrip, params ToolStripButton[] specialButtons)
        {
            toolStrip.Renderer = new SatisfactoryToolStripRenderer(specialButtons);
            
            foreach(ToolStripButton b in specialButtons)
            {
                b.Font = GetVariantFont(b, true);
                b.AutoSize = true;
            }
        }

        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
        {
/*
            base.OnRenderToolStripBackground(e);
            return;
*/
            
            Rectangle all = e.ToolStrip.ClientRectangle;
            
            LinearGradientBrush lgb = new LinearGradientBrush(
                all,
                SystemColors.ControlLightLight,
                SystemColors.ControlDark,
                90f);

            lgb.Blend = _MyBlend;
            e.Graphics.FillRectangle(lgb, e.AffectedBounds);
        }
        
        static Font GetVariantFont(ToolStripButton b, bool isChecked)
        {
            Font f = b.Font;
            Control control = b.Owner;
            while (f == null && control != null)
            {
                f = control.Font;
                control = control.Parent;
            }
            if (f == null)
                f = SystemFonts.DialogFont;

            Font ret = new Font(f.Name, f.Size, isChecked ?  FontStyle.Bold : FontStyle.Regular);
            return ret;
        }


        protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;

            ToolStripButton b = e.Item as ToolStripButton;
            if (b != null)
            {
                bool isSpecial = Array.IndexOf(_SpecialButtons, b) >= 0;
                if (isSpecial)
                    e.TextFont = GetVariantFont(b, b.Checked);
                
                if (b.Checked)
                {
                    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    Color prevColor = e.TextColor;
                    e.TextColor = MyColorTable.Bright(ColorTable.ButtonPressedGradientEnd, 9);
                    Rectangle rect = e.TextRectangle;
                    e.TextRectangle = Rectangle.FromLTRB(rect.Left + 1, rect.Top + 1, rect.Right, rect.Bottom);
                    // base.OnRenderItemText(e);

                    e.TextRectangle = rect;
                    e.TextColor = prevColor;
                    base.OnRenderItemText(e);
                }
                else
                {
                    base.OnRenderItemText(e);
                }
            }
            
            else
                base.OnRenderItemText(e);
        }

        protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
        {
/*
            base.OnRenderButtonBackground(e);
            return;
*/

            Color
                cb, ce;

            float borderFactor = 0.2f;

            ToolStripButton b = e.Item as ToolStripButton;
            Blend blend = null;

            if (b.Pressed)
            {
                cb = this.ColorTable.ButtonPressedGradientBegin;
                ce = this.ColorTable.ButtonPressedGradientEnd;
                borderFactor = 0.5f;
                blend = _MyBackBlend;
            }
            
            else if (b.Selected)
            {
                cb = this.ColorTable.ButtonSelectedGradientBegin;
                ce = this.ColorTable.ButtonSelectedGradientEnd;
                blend = _MyBlend;
            }
            
            else if (b.Checked)
            {
                cb = this.ColorTable.ButtonCheckedGradientBegin;
                ce = this.ColorTable.ButtonCheckedGradientEnd;
                borderFactor = 0.8f;
                blend = _MyBackBlend;
            }
            
            else
            {
                return;
            }

            borderFactor = 0.4f;
            Color border = ColorInfo.Blend(SystemColors.ActiveCaption, SystemColors.ControlDark, borderFactor);
            border = SystemColors.ControlDark;
            Rectangle rect = b.ContentRectangle;
            rect.Inflate(-5, 0);
            rect = new Rectangle(0, 0, b.Size.Width - 1, b.Size.Height - 1);
/*
            Debug.WriteLine("Button " + b.Name + " bounds: " + b.Bounds + "; Content: " + b.ContentRectangle);
            e.Graphics.DrawRectangle(new Pen(border), rect);
            return;
*/
            // RoundRectPath pathInfo = new RoundRectPath(rect, 3, RoundRectPath.Shape.CutRect);
            Size roundSize = new Size(rect.Height / 4, rect.Height / 3);
            roundSize = new Size(rect.Height/6, rect.Height/3);
            
            RoundRectPath pathInfo = new RoundRectPath(rect, roundSize, RoundRectPath.Shape.RoundRect);
            GraphicsPath gp = pathInfo.GraphicsPath;

            LinearGradientBrush lgb = new LinearGradientBrush(
                rect,
                cb,
                ce,
                90f);

            if (blend != null)
                lgb.Blend = blend;
            
            // e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            // e.Graphics.InterpolationMode = InterpolationMode.Bilinear;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.SetClip(gp);
            e.Graphics.FillRectangle(lgb, rect);
            e.Graphics.ResetClip();

            e.Graphics.DrawPath(new Pen(border), gp);
        }
    }
    
    class MyColorTable: ProfessionalColorTable
    {
        public override Color SeparatorDark
        {
            get { return Bright(SystemColors.ButtonShadow, -1); }
        }

        public override Color SeparatorLight
        {
            get { return Bright(SystemColors.ButtonShadow, 11); }
        }

        BaseColors Base
        {
            get
            {
                // return new BaseColors(SystemColors.ActiveCaption, SystemColors.GradientActiveCaption, SystemColors.GradientActiveCaption);
                return new BaseColors(ControlPaint.Dark(SystemColors.Control), ControlPaint.Light(SystemColors.Control), ControlPaint.Dark(SystemColors.Control));
            }
        }
        
        // checked, mouse out
        public override Color ButtonCheckedGradientBegin
        {
            get { return Bright(Base.Checked, 1); }
        }

        public override Color ButtonCheckedGradientMiddle
        {
            get { return Bright(ButtonCheckedGradientBegin, 4); }
        }

        public override Color ButtonCheckedGradientEnd
        {
            get { return Bright(Base.Checked, 9); }
        }

/*
        // not used
        public override Color CheckBackground
        {
            get { return Color.Red; }
        }

        public override Color CheckSelectedBackground
        {
            get { return base.CheckSelectedBackground; }
        }

        public override Color CheckPressedBackground
        {
            get { return base.CheckPressedBackground; }
        }
        

        // not used
        public override Color ButtonCheckedHighlight
        {
            get { return Color.Green; }
        }

        // not used
        public override Color ButtonCheckedHighlightBorder
        {
            get { return Color.Green; }
        }
*/

        // background?
        public override Color ToolStripGradientBegin
        {
            get { return SystemColors.ControlLightLight; }
        }

        public override Color ToolStripGradientMiddle
        {
            get { return SystemColors.ControlLight; }
        }

        public override Color ToolStripGradientEnd
        {
            get { return SystemColors.ControlDark; }
        }


        // hover
        public override Color ButtonSelectedGradientBegin
        {
            get { return Bright(Base.Selected, 7); }
        }

        public override Color ButtonSelectedGradientMiddle
        {
            get { return Bright(Base.Selected, 4); }
        }

        public override Color ButtonSelectedGradientEnd
        {
            get { return Bright(Base.Selected, 1); }
        }


        // pressed
        public override Color ButtonPressedGradientBegin
        {
            get { return Bright(Base.Pressed, -1); }
        }

        public override Color ButtonPressedGradientMiddle
        {
            get { return Bright(Base.Pressed, -1); }
        }

        public override Color ButtonPressedGradientEnd
        {
            get { return Bright(Base.Pressed, 5); }
        }


        internal static Color Bright(Color c, int n)
        {
            const float k = 0.9f;
            for (int i = 0; i < Math.Abs(n); i++)
                c = n>0 ? ControlPaint.Light(c) : Color.FromArgb((int)(c.R*k),(int)(c.G*k), (int)(c.B*k));
            
            return c;
        }

        /*
        public override Color CheckBackground
        {
            get { return Color.Red; }
        }


        public override Color ToolStripBorder
        {
            get { return Color.Yellow; }
        }
*/
        class BaseColors
        {
            public readonly Color
                Checked,
                Pressed,
                Selected;

            public BaseColors(Color @checked, Color pressed, Color selected)
            {
                Checked = @checked;
                Pressed = pressed;
                Selected = selected;
            }
        }
        
    }
}
